package geppetto.cat.common;

import java.io.PrintStream;

public class Common {

	// matrix is indexes by (source,foreign). normalize for foreign
	public static double[][] normalize(double[][] p, int foreign, int source) {

		for (int i = 0; i < foreign; i++) {
			double sum = 0;
			for (int j = 0; j < source; j++) {
				sum += p[j][i];
			}
			if (sum != 0) {
				for (int j = 0; j < source; j++) {
					p[j][i] = p[j][i] / sum;
				}
				// System.err.println("Ok");
			} else
				System.err
						.println("Error normalizer is zero: Failing this istance");
		}
		return p;
	}

	/*
	 * q and p are indexed by source/foreign Sum_S(q) = 1 the same for p KL(q,p) =
	 * Eq*q/p
	 */
	public static double KLDistance(double[][] p, double[][] q, int sourceSize,
			int foreignSize) {
		double totalKL = 0;
		for (int i = 0; i < sourceSize; i++) {
			double kl = 0;
			for (int j = 0; j < foreignSize; j++) {
				assert !Double.isNaN(q[i][j]) : "KLDistance q:  prob is NaN";
				assert !Double.isNaN(p[i][j]) : "KLDistance p:  prob is NaN";
				if (p[i][j] == 0 || q[i][j] == 0) {
					continue;
				} else {
					kl += q[i][j] * Math.log(q[i][j] / p[i][j]);
				}

			}
			totalKL += kl;
		}
		assert !Double.isNaN(totalKL) : "KLDistance: prob is NaN";
		return totalKL / sourceSize;
	}

	/*
	 * indexed the by [fi][si]
	 */
	public static double KLDistancePrime(double[][] p, double[][] q,
			int sourceSize, int foreignSize) {
		double totalKL = 0;
		for (int i = 0; i < sourceSize; i++) {
			double kl = 0;
			for (int j = 0; j < foreignSize; j++) {
				assert !Double.isNaN(q[j][i]) : "KLDistance q:  prob is NaN";
				assert !Double.isNaN(p[j][i]) : "KLDistance p:  prob is NaN";
				if (p[j][i] == 0 || q[j][i] == 0) {
					continue;
				} else {
					kl += q[j][i] * Math.log(q[j][i] / p[j][i]);
				}

			}
			totalKL += kl;
		}
		assert !Double.isNaN(totalKL) : "KLDistance: prob is NaN";
		return totalKL / sourceSize;
	}

	public static double Entropy(double[][] p, int sourceSize, int foreignSize) {
		double totalE = 0;
		for (int i = 0; i < foreignSize; i++) {
			double e = 0;
			for (int j = 0; j < sourceSize; j++) {
				e += p[i][j] * Math.log(p[i][j]);
			}
			totalE += e;
		}
		return totalE / sourceSize;
	}

	public static double[][] copyMatrix(double[][] original, int sourceSize,
			int foreignSize) {
		double[][] result = new double[sourceSize][foreignSize];
		for (int i = 0; i < sourceSize; i++) {
			for (int j = 0; j < foreignSize; j++) {
				result[i][j] = original[i][j];
			}
		}
		return result;
	}

	public static void printMatrix(double[][] matrix, int sourceSize,
			int foreignSize, String info, PrintStream out) {

		java.text.DecimalFormat fmt = new java.text.DecimalFormat();
		fmt.setMaximumFractionDigits(10);
		fmt.setMaximumIntegerDigits(10);
		fmt.setMinimumFractionDigits(10);
		fmt.setMinimumIntegerDigits(10);

		out.println(info);
		out.println("Lines are source probabilites for a given foreign");
		for (int i = 0; i < foreignSize; i++) {
			for (int j = 0; j < sourceSize; j++) {
				out.print(fmt.format(matrix[j][i] * 1000000) + " ");
			}
			out.println();
		}
		out.println();
		out.println();
	}

	public static void main(String[] args) {

	}

}
